package ecscore

import (
	"unsafe"

	"github.com/nwillc/genfuncs"
	"github.com/nwillc/genfuncs/container"
)

type QueryResultIterator[T any] struct {
	Item    T
	storage EntityStorage
	query   *Query[T]
	ptr     unsafe.Pointer
	ids     []EntityId
	index   uint32
}

func (q *QueryResultIterator[T]) Sort() {
	cmptor := func(a EntityId, b EntityId) bool {
		return genfuncs.OrderedLessThan(a)(b)
	}
	container.GSlice[uint32](q.ids).SortBy(cmptor)
}

func (q *QueryResultIterator[T]) Get() *T {
	if q.index >= uint32(len(q.ids)) {
		return nil
	}

	var genericTy T
	res := &genericTy
	q.query.Read(q.storage, q.ids[q.index], unsafe.Pointer(res))
	return res
}

func (q *QueryResultIterator[T]) Next() bool {
	if q.index >= uint32(len(q.ids)) {
		return false
	}

	id := q.ids[q.index]
	q.query.Read(q.storage, id, q.ptr)
	q.index += 1
	return true
}

func (q *QueryResultIterator[T]) ToList() []T {
	result := make([]T, len(q.ids))
	for idx := range result {
		q.query.Read(q.storage, q.ids[idx], unsafe.Pointer(&result[idx]))
	}

	return result
}

func (q *QueryResultIterator[T]) First() (T, bool) {
	var genericTy T
	if len(q.ids) == 0 {
		return genericTy, false
	}

	id := q.ids[0]
	q.query.Read(q.storage, id, unsafe.Pointer(&genericTy))
	return genericTy, true
}
